Java Review =========== Relevant chapters: 1-4 We will not go over these in any detail. We will only highlight some important topics for CS 235 (e.g., packages), mostly via examples and using the first lab assignment as a guide. Development Tools ----------------- Create a "root" directory for CS 235 on your computer. Everything should be saved under this directory and its sub-directories. Making sure Java is "visible" Update your "path" environment variable [path=%path%;c:\jdk\bin] Writing code (a) Start -> Programs -> Your Favorite Editor (e.g., emacs, crimson, wordpad, smultron) (b) Link your .java extension to some editor of choice (c) Use your favorite IDE (e.g., Eclipse, NetBeans) (note that pass-off requires command-line) Compiling your code (a) DOS command line (Start -> Run -> "cmd") [javac -cp packageRoot package1\package2\ ... \packageN\YourClass.java] (b) cygwin/linus/unix [javac -cp packageRoot package1/package2/ ... /packageN/YourClass.java] (c) Your favorite IDE [compile menu option] Executing your code (a) DOS command line [java -cp packageRoot package1.package2. ... .packageN.YourClass] (b) cygwin/linux/unix [java -cp packageRoot package1.package2. ... .packageN.YourClass] (c) Your favorite IDE [run menu option] (Note: We return to the package issue below. The "-cp" option is used when the current directory is not the root of the packages. I tend to use it by default.If you are in the root directory, then use "-cp ./".) Command-line Arguments ---------------------- What are command-line arguments? How do you access command-line arguments in a Java program? (a) Demo1 (print the command line args) (b) Demo2 (compute the sum of the command-line arguments) (c) Demo3 (catching exceptions: non-numeric argument) Input-Output ------------ Reading from a text file (rather than the command line) (a) Demo4 (read from a file - no file exception, single line/single num) [General syntax: import java.io.* BufferedReader in = new BufferedReader( new InputStreamReader(System.in)); BufferedReader in = new BufferedReader( new FileReader("foobar")); line = in.readLine(); in.close();] (b) Demo5 (read from a file - file exception, single line/single num) [Catching exception: void method() throws IOException ... try { } catch (IOException e) { System.out.println(e); }] (c) Demo6 (read from a file - multiple lines/single num) [Detecting end of file: if (line == null) return;] (d) Demo7 (read from a file - multiple lines/multiple num) [Alternatively: StringTokenizer st = new StringTokenizer(line); st.countTokens() tok = st.nextToken()] (see Demo7a) Writing to a text file (a) Demo8 (write to file - close) [General syntax: FileWriter fw = new FileWriter("file.txt"); PrintWriter pw = new PrintWriter(fw); pw.print(); pw.println(); pw.close();] (b) Demo9 (write to file - no close) Throwing Exceptions ------------------- When should you cause exceptions to be thrown? (a) Demo10 (setting a bit to an illegal value) Programming with Objects ------------------------ An object is an abstract data type, which encapsulates both structure and function. It contains: - Variables (data, attributes) - Methods (operations, behaviors) Variables define the possible states of an object, whilst methods define its possible behaviors. Instance variables should be declared private and accessed only via adequate functions: - mutators (setters) change the state of an object - accessors (getters) read the state of an object Each class should have a single "main" method. This allows classes to be tested individually (unit testing). (a) Book1 (no error checking, no toString()) Mutators need to check for valid values to preserve the integrity of objects (i.e., guarantee that only valid states are reached). Adequate display of objects is achieved with the "toString" method (public String toString()). (b) Book2 (error checking, adequate display) To avoid duplication of code, constructors shoud generally call the appropriate mutators. To check whether two objects are the same, collection classes must use the "equals" method (public boolean equals(Object obj)). (c) Library Using Packages -------------- Packages are used to organize collections of classes in some logical fashion. Packages are organized hierarchically, like directories, with names separated by "." (e.g., java.io, pack1.sub2.bib) Let C be a class to be included in package P. Then - The first line of C should be "package P;" - The source for C must be placed in the P subdirectory - Any class making use of C must include "import P.C;" The package structure MUST match the directory structure exactly. Starting in the current directory (known as "PackageRoot" below) (a) put Library in library package [create subdirectory "library" in local directory move Library.java to library add "package library;" as first line of Library.java] (b) put Book and Video in library.holdings package [create subdirectory "holdings" in directory library move Book.java and Video.java to library/holdings add "package library.holdings;" as first line of Book.java and Video.java] (c) add "import library.holdings.Book;" and "import library.holdings.Video;" to Library.java, since it makes use of these classes (d) make sure that javac uses the full path to compile the classes: [Assuming I am in "PackageRoot": javac -cp ./ library/holdings/Book.java javac -cp ./ library/holdings/Video.java javac -cp ./ library/Library.java ] [Assuming I am in "PackageRoot/library": javac -cp .. holdings/Book.java javac -cp .. holdings/Video.java javac -cp .. Library.java ] [Assuming I am in "PackageRoot/library/holdings": javac -cp ../.. Book.java (or simply javac Book.java) javac -cp ../.. Video.java (or simply javac Video.java) javac -cp ../.. ../Library.java ] [Assuming I am anywhere else: javac -cp RelativePathToPackageRoot RelativePathToPackageRoot/library/holdings/Book.java javac -cp RelativePathToPackageRoot RelativePathToPackageRoot/library/holdings/Video.java javac -cp RelativePathToPackageRoot RelativePathToPackageRoot/library/Library.java ] (e) make sure you completely specify the class for execution, i.e., what package it belongs to: [Assuming I am in "PackageRoot": java -cp ./ library.Library ] [Assuming I am in "PackageRoot/library": java -cp .. library.Library ] [Assuming I am anywhere else: java -cp RelativePathToPackageRoot library.Library ] Using Interfaces ---------------- Notice that the Library object implements its holdings as a an array of Object. This allows any object to be added to our library (since all objects in Java inherit from the generic Object class. Although this is convenient, it may be too loose, in that, not only can Book objects and Video objects be added, but also any other. There are at least two ways to restrict the Library to only accept Book and Video objects. 1. Use an interface: a. Create a Holding interface b. Have both Book and Video implement the Holding interface c. Put setTitle/getTitle into Holding interface, leave implementation of setTitle/getTitle in Book/Video d. Change Library to use array of Holding 2. Use a class hierarchy: a. Create a class Holding b. Make both Book and Video inherit from Holding c. Change Library to use array of Holding Both allow full control over what can be added to Library. The first solution, however, results in some code duplication since the two functions have to be implemented in each class (Book and Video). Note that both solutions may also be combined by creating a Holding interface, creating a class HoldingImpl that implements the Holding interface, and have both Book and Video inherit (i.e., extend) the HoldingImpl class. Finally, a note on "Comparable" How can you make the Library sort its holdings by title? 1. Add sort method to Library class [java.util.Arrays.sort(holdings, 0, count);] 2. In order for the sorting to work, Book and Video must implement Comparable 3. As both inherit from HoldingImpl, it makes sense to have HoldingImpl implement Comparable See final code in library/holdings1 Using GUI Things ---------------- See simple examples of various events in folder "Basic GUI Things"